home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / pstatmnt.pas < prev    next >
Pascal/Delphi Source File  |  1998-09-24  |  41KB  |  1,183 lines

  1. {
  2.     $Id: pstatmnt.pas,v 1.3.2.1 1998/08/05 14:07:34 pierre Exp $
  3.     Copyright (c) 1998 by Florian Klaempfl
  4.  
  5.     Does the parsing of the statements
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  ****************************************************************************
  22. }
  23. unit pstatmnt;
  24.  
  25.   interface
  26.  
  27.     uses tree;
  28.  
  29.     var
  30.        { true, if we are in a except block }
  31.        in_except_block : boolean;
  32.  
  33.     { reads a block }
  34.     function block(islibrary : boolean) : ptree;
  35.  
  36.     { reads an assembler block }
  37.     function assembler_block : ptree;
  38.  
  39.   implementation
  40.  
  41.     uses
  42.        cobjects,scanner,globals,symtable,aasm,pass_1,
  43.        types,hcodegen,files,verbose
  44.        { processor specific stuff }
  45. {$ifdef i386}
  46.        ,i386
  47.        ,rai386
  48.        ,ratti386
  49.        ,radi386
  50.        ,tgeni386
  51. {$endif}
  52. {$ifdef m68k}
  53.        ,m68k
  54.        ,tgen68k
  55.        ,ag68kmit
  56.        ,ra68k
  57.        ,ag68kgas
  58.        ,ag68kmot
  59. {$endif}
  60.        { parser specific stuff, be careful consume is also defined to }
  61.        { read assembler tokens                                        }
  62.        ,pbase,pexpr,pdecl;
  63.  
  64.  
  65.     function statement : ptree;forward;
  66.  
  67.     function if_statement : ptree;
  68.  
  69.       var
  70.          ex,if_a,else_a : ptree;
  71.  
  72.       begin
  73.          consume(_IF);
  74.          ex:=expr;
  75.          consume(_THEN);
  76.          if token<>_ELSE then
  77.            if_a:=statement
  78.          else
  79.        if_a:=nil;
  80.  
  81.          if token=_ELSE then
  82.            begin
  83.               consume(_ELSE);
  84.               else_a:=statement;
  85.            end
  86.          else
  87.            else_a:=nil;
  88.          if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  89.       end;
  90.  
  91.     { creates a block (list) of statements, til the next END token }
  92.     function statements_til_end : ptree;
  93.  
  94.       var
  95.          first,last : ptree;
  96.  
  97.       begin
  98.          first:=nil;
  99.          while token<>_END do
  100.            begin
  101.               if first=nil then
  102.                 begin
  103.                    last:=gennode(anwein,nil,statement);
  104.                    first:=last;
  105.                 end
  106.               else
  107.                 begin
  108.                    last^.left:=gennode(anwein,nil,statement);
  109.                    last:=last^.left;
  110.                 end;
  111.               if token<>SEMICOLON then
  112.                 break
  113.               else
  114.                 consume(SEMICOLON);
  115.               while token=SEMICOLON do
  116.                 consume(SEMICOLON);
  117.  
  118.            end;
  119.          consume(_END);
  120.          statements_til_end:=gensinglenode(blockn,first);
  121.       end;
  122.  
  123.     function case_statement : ptree;
  124.  
  125.       var
  126.          { contains the label number of currently parsed case block }
  127.          aktcaselabel : plabel;
  128.          wurzel : pcaserecord;
  129.  
  130.          { the typ of the case expression }
  131.          casedef : pdef;
  132.  
  133.       procedure newcaselabel(l,h : longint);
  134.  
  135.         var
  136.            hcaselabel : pcaserecord;
  137.  
  138.         procedure insertlabel(var p : pcaserecord);
  139.  
  140.           begin
  141.              if p=nil then p:=hcaselabel
  142.              else
  143.                 if (p^._low>hcaselabel^._low) and
  144.                    (p^._low>hcaselabel^._high) then
  145.                   insertlabel(p^.less)
  146.                 else if (p^._high<hcaselabel^._low) and
  147.                    (p^._high<hcaselabel^._high) then
  148.                   insertlabel(p^.greater)
  149.                 else Message(parser_e_double_caselabel);
  150.           end;
  151.  
  152.         begin
  153.            new(hcaselabel);
  154.            hcaselabel^.less:=nil;
  155.            hcaselabel^.greater:=nil;
  156.            hcaselabel^.statement:=aktcaselabel;
  157.            getlabel(hcaselabel^._at);
  158.            hcaselabel^._low:=l;
  159.            hcaselabel^._high:=h;
  160.            insertlabel(wurzel);
  161.         end;
  162.  
  163.       var
  164.          code,caseexpr,p,instruc,elseblock : ptree;
  165.          hl1,hl2 : longint;
  166.          ranges : boolean;
  167.  
  168.       begin
  169.          consume(_CASE);
  170.          caseexpr:=expr;
  171.          { determines result type }
  172.          cleartempgen;
  173.          do_firstpass(caseexpr);
  174.          casedef:=caseexpr^.resulttype;
  175.  
  176.          if not(is_ordinal(casedef)) then
  177.            Message(parser_e_ordinal_expected);
  178.  
  179.          consume(_OF);
  180.          wurzel:=nil;
  181.          ranges:=false;
  182.          instruc:=nil;
  183.          repeat
  184.            getlabel(aktcaselabel);
  185.            {aktcaselabel^.is_used:=true; }
  186.  
  187.            { an instruction has may be more case labels }
  188.            repeat
  189.              p:=expr;
  190.              cleartempgen;
  191.              do_firstpass(p);
  192.  
  193.              if (p^.treetype=rangen) then
  194.                begin
  195.                   { type checking for case statements }
  196.                   if not is_subequal(casedef, p^.left^.resulttype) then
  197.                     Message(parser_e_case_mismatch);
  198.                   { type checking for case statements }
  199.                   if not is_subequal(casedef, p^.right^.resulttype) then
  200.                     Message(parser_e_case_mismatch);
  201.                   hl1:=get_ordinal_value(p^.left);
  202.                   hl2:=get_ordinal_value(p^.right);
  203.                   testrange(casedef,hl1);
  204.                   testrange(casedef,hl2);
  205.                   newcaselabel(hl1,hl2);
  206.                   ranges:=true;
  207.                end
  208.              else
  209.                begin
  210.                   { type checking for case statements }
  211.                   if not is_subequal(casedef, p^.resulttype) then
  212.                     Message(parser_e_case_mismatch);
  213.                     hl1:=get_ordinal_value(p);
  214.                     testrange(casedef,hl1);
  215.                     newcaselabel(hl1,hl1);
  216.                end;
  217.              disposetree(p);
  218.              if token=COMMA then consume(COMMA)
  219.                else break;
  220.            until false;
  221.            consume(COLON);
  222.  
  223.            { handles instruction block }
  224.            p:=gensinglenode(labeln,statement);
  225.            p^.labelnr:=aktcaselabel;
  226.  
  227.            { concats instruction }
  228.            instruc:=gennode(anwein,instruc,p);
  229.  
  230.            if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
  231.              consume(SEMICOLON);
  232.          until (token=_ELSE) or (token=_OTHERWISE) or (token=_END);
  233.  
  234.          if (token=_ELSE) or (token=_OTHERWISE) then
  235.            begin
  236.               if token=_ELSE then consume(_ELSE)
  237.                 else consume(_OTHERWISE);
  238.               elseblock:=statements_til_end;
  239.            end
  240.          else
  241.            begin
  242.               elseblock:=nil;
  243.               consume(_END);
  244.            end;
  245.  
  246.          code:=gencasenode(caseexpr,instruc,wurzel);
  247.  
  248.          code^.elseblock:=elseblock;
  249.  
  250.          case_statement:=code;
  251.       end;
  252.  
  253.     function repeat_statement : ptree;
  254.  
  255.       var
  256.          first,last,p_e : ptree;
  257.  
  258.       begin
  259.          consume(_REPEAT);
  260.          first:=nil;
  261.          while token<>_UNTIL do
  262.            begin
  263.               if first=nil then
  264.                 begin
  265.                    last:=gennode(anwein,nil,statement);
  266.                    first:=last;
  267.                 end
  268.               else
  269.                 begin
  270.                    last^.left:=gennode(anwein,nil,statement);
  271.                    last:=last^.left;
  272.                 end;
  273.               if token<>SEMICOLON then
  274.                 break;
  275.               consume(SEMICOLON);
  276.               while token=SEMICOLON do
  277.                 consume(SEMICOLON);
  278.            end;
  279.          consume(_UNTIL);
  280.          first:=gensinglenode(blockn,first);
  281.          p_e:=expr;
  282.          repeat_statement:=genloopnode(repeatn,p_e,first,nil,false);
  283.       end;
  284.  
  285.     function while_statement : ptree;
  286.  
  287.       var
  288.          p_e,p_a : ptree;
  289.  
  290.       begin
  291.          consume(_WHILE);
  292.      p_e:=expr;
  293.          consume(_DO);
  294.          p_a:=statement;
  295.          while_statement:=genloopnode(whilen,p_e,p_a,nil,false);
  296.       end;
  297.  
  298.     function for_statement : ptree;
  299.  
  300.       var
  301.          p_e,tovalue,p_a : ptree;
  302.          backward : boolean;
  303.  
  304.       begin
  305.          { parse loop header }
  306.          consume(_FOR);
  307.          p_e:=expr;
  308.          if token=_DOWNTO then
  309.            begin
  310.               consume(_DOWNTO);
  311.               backward:=true;
  312.            end
  313.          else
  314.            begin
  315.               consume(_TO);
  316.               backward:=false;
  317.            end;
  318.          tovalue:=expr;
  319.          consume(_DO);
  320.  
  321.          { ... now the instruction }
  322.                  p_a:=statement;
  323.                  for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  324.           end;
  325.  
  326.     function _with_statement : ptree;
  327.  
  328.       var
  329.          right,hp,p : ptree;
  330.          i,levelcount : longint;
  331.          withsymtable,symtab : psymtable;
  332.          obj : pobjectdef;
  333.  
  334.       begin
  335.          Must_be_valid:=false;
  336.          p:=expr;
  337.          do_firstpass(p);
  338.          right:=nil;
  339.          case p^.resulttype^.deftype of
  340.             objectdef : begin
  341.                           obj:=pobjectdef(p^.resulttype);
  342.                           levelcount:=0;
  343.                           while assigned(obj) do
  344.                             begin
  345.                                symtab:=obj^.publicsyms;
  346.                                withsymtable:=new(psymtable,init(symtable.withsymtable));
  347.                                withsymtable^.wurzel:=symtab^.wurzel;
  348.                                withsymtable^.next:=symtablestack;
  349.                                symtablestack:=withsymtable;
  350.                                obj:=obj^.childof;
  351.                                inc(levelcount);
  352.                             end;
  353.                        end;
  354.             recorddef : begin
  355.                            symtab:=precdef(p^.resulttype)^.symtable;
  356.                            levelcount:=1;
  357.                            withsymtable:=new(psymtable,init(symtable.withsymtable));
  358.                            withsymtable^.wurzel:=symtab^.wurzel;
  359.                            withsymtable^.next:=symtablestack;
  360.                            symtablestack:=withsymtable;
  361.                         end;
  362.             else
  363.               begin
  364.                     Message(parser_e_false_with_expr);
  365.                     { try to recover from error }
  366.                     if token=COMMA then
  367.                       begin
  368.                          consume(COMMA);
  369. {$ifdef tp}
  370.                                                  hp:=_with_statement;
  371. {$else}
  372.                                                  hp:=_with_statement();
  373. {$endif}
  374.                                           end
  375.                                         else
  376.                                           begin
  377.                                                  consume(_DO);
  378.                                                  { ignore all }
  379.                                                  if token<>SEMICOLON then
  380.                                                    statement;
  381.                       end;
  382.                     _with_statement:=nil;
  383.                     exit;
  384.                  end;
  385.          end;
  386.          if token=COMMA then
  387.            begin
  388.               consume(COMMA);
  389. {$ifdef tp}
  390.                           right:=_with_statement;
  391. {$else}
  392.               right:=_with_statement();
  393. {$endif}
  394.            end
  395.          else
  396.            begin
  397.               consume(_DO);
  398.               if token<>SEMICOLON then
  399.                 right:=statement
  400.               else
  401.                 right:=nil;
  402.            end;
  403.          for i:=1 to levelcount do
  404.            symtablestack:=symtablestack^.next;
  405.  
  406.          _with_statement:=genwithnode(withsymtable,p,right,levelcount);
  407.       end;
  408.  
  409.     function with_statement : ptree;
  410.  
  411.       begin
  412.          consume(_WITH);
  413.          with_statement:=_with_statement;
  414.       end;
  415.  
  416.     function raise_statement : ptree;
  417.  
  418.       var
  419.          p1,p2 : ptree;
  420.  
  421.       begin
  422.          p1:=nil;
  423.          p2:=nil;
  424.          consume(_RAISE);
  425.          if token<>SEMICOLON then
  426.            begin
  427.               p1:=expr;
  428.               if (token=ID) and (pattern='AT') then
  429.                 begin
  430.                    consume(ID);
  431.                    p2:=expr;
  432.                 end;
  433.            end
  434.          else
  435.            begin
  436.               if not(in_except_block) then
  437.                Message(parser_e_no_reraise_possible);
  438.            end;
  439.          raise_statement:=gennode(raisen,p1,p2);
  440.       end;
  441.  
  442.     function try_statement : ptree;
  443.  
  444.       var
  445.          p_try_block,p_finally_block,first,last,
  446.          p_default,e1,e2,p_specific : ptree;
  447.  
  448.          old_in_except_block : boolean;
  449.  
  450.       begin
  451.          p_default:=nil;
  452.          p_specific:=nil;
  453.  
  454.          { read statements to try }
  455.          consume(_TRY);
  456.          first:=nil;
  457.          while (token<>_FINALLY) and (token<>_EXCEPT) do
  458.                    begin
  459.               if first=nil then
  460.                 begin
  461.                                    last:=gennode(anwein,nil,statement);
  462.                    first:=last;
  463.                 end
  464.               else
  465.                 begin
  466.                                    last^.left:=gennode(anwein,nil,statement);
  467.                    last:=last^.left;
  468.                 end;
  469.                           if token<>SEMICOLON then
  470.                                 break;
  471.                           consume(SEMICOLON);
  472.                           emptystats;
  473.                    end;
  474.          p_try_block:=gensinglenode(blockn,first);
  475.  
  476.          if token=_FINALLY then
  477.            begin
  478.               consume(_FINALLY);
  479.               p_finally_block:=statements_til_end;
  480.               try_statement:=gennode(tryfinallyn,p_try_block,p_finally_block);
  481.            end
  482.          else
  483.            begin
  484.               consume(_EXCEPT);
  485.               old_in_except_block:=in_except_block;
  486.               in_except_block:=true;
  487.  
  488.               if token=_ON then
  489.                 { catch specific exceptions }
  490.                 begin
  491.                    repeat
  492.                      consume(_ON);
  493.              e1:=expr;
  494.                      if token=COLON then
  495.                        begin
  496.                           consume(COLON);
  497.               e2:=expr;
  498.                           { !!!!! }
  499.                        end
  500.                      else
  501.                        begin
  502.                           { !!!!! }
  503.                        end;
  504.                      consume(_DO);
  505.                                          statement;
  506.                                          if token<>SEMICOLON then
  507.                                            break;
  508.                                          emptystats;
  509.                                    until false;
  510.                    if token=_ELSE then
  511.                      { catch the other exceptions }
  512.                      begin
  513.                         consume(_ELSE);
  514.                         p_default:=statements_til_end;
  515.                      end;
  516.                 end
  517.               else
  518.                 { catch all exceptions }
  519.                 begin
  520.                    p_default:=statements_til_end;
  521.                 end;
  522.               in_except_block:=old_in_except_block;
  523.               try_statement:=genloopnode(tryexceptn,p_try_block,p_specific,p_default,false);
  524.            end;
  525.       end;
  526.  
  527.     function exit_statement : ptree;
  528.  
  529.       var
  530.          p : ptree;
  531.  
  532.       begin
  533.          consume(_EXIT);
  534.          if token=LKLAMMER then
  535.            begin
  536.               consume(LKLAMMER);
  537.           p:=expr;
  538.               consume(RKLAMMER);
  539.               if procinfo.retdef=pdef(voiddef) then
  540.                 Message(parser_e_void_function);
  541.            end
  542.          else
  543.            p:=nil;
  544.          exit_statement:=gensinglenode(exitn,p);
  545.       end;
  546.  
  547.  
  548. {$ifdef i386}
  549.     function _asm_statement : ptree;
  550.  
  551.       begin
  552.          case aktasmmode of
  553.             I386_ATT : _asm_statement:=ratti386.assemble;
  554.             I386_INTEL : _asm_statement:=rai386.assemble;
  555.             I386_DIRECT : _asm_statement:=radi386.assemble;
  556.             else internalerror(30004);
  557.          end;
  558.  
  559.          { Erst am Ende _ASM konsumieren, da der Scanner sonst die }
  560.          { erste Assemblerstatement zu lesen versucht! }
  561.          consume(_ASM);
  562.  
  563.          { (END is read) }
  564.          if token=LECKKLAMMER then
  565.            begin
  566.               { it's possible to specify the modified registers }
  567.               consume(LECKKLAMMER);
  568.               if token<>RECKKLAMMER then
  569.                 repeat
  570.                   pattern:=upper(pattern);
  571.                   if pattern='EAX' then
  572.                     usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  573.                   else if pattern='EBX' then
  574.                     usedinproc:=usedinproc or ($80 shr byte(R_EBX))
  575.                   else if pattern='ECX' then
  576.                     usedinproc:=usedinproc or ($80 shr byte(R_ECX))
  577.                   else if pattern='EDX' then
  578.                     usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  579.                   else if pattern='ESI' then
  580.                     usedinproc:=usedinproc or ($80 shr byte(R_ESI))
  581.                   else if pattern='EDI' then
  582.                     usedinproc:=usedinproc or ($80 shr byte(R_EDI))
  583.                   else consume(RECKKLAMMER);
  584.                   consume(CSTRING);
  585.                   if token=COMMA then consume(COMMA)
  586.                     else break;
  587.                 until false;
  588.               consume(RECKKLAMMER);
  589.            end
  590.          else usedinproc:=$ff;
  591.       end;
  592. {$endif}
  593.  
  594. {$ifdef m68k}
  595.     function _asm_statement : ptree;
  596.     begin
  597.          _asm_statement:= ra68k.assemble;
  598.          { Erst am Ende _ASM konsumieren, da der Scanner sonst die }
  599.          { erste Assemblerstatement zu lesen versucht! }
  600.          consume(_ASM);
  601.  
  602.          { (END is read) }
  603.          if token=LECKKLAMMER then
  604.            begin
  605.               { it's possible to specify the modified registers }
  606.               { we only check the registers which are not reserved }
  607.               { and which can be used. This is done for future     }
  608.               { optimizations.                                     }
  609.               consume(LECKKLAMMER);
  610.               if token<>RECKKLAMMER then
  611.                 repeat
  612.                   pattern:=upper(pattern);
  613.                   if pattern='D0' then
  614.                     usedinproc:=usedinproc or ($800 shr word(R_D0))
  615.                   else if pattern='D1' then
  616.                     usedinproc:=usedinproc or ($800 shr word(R_D1))
  617.                   else if pattern='D6' then
  618.                     usedinproc:=usedinproc or ($800 shr word(R_D6))
  619.                   else if pattern='A0' then
  620.                     usedinproc:=usedinproc or ($800 shr word(R_A0))
  621.                   else if pattern='A1' then
  622.                     usedinproc:=usedinproc or ($800 shr word(R_A1))
  623.                   else consume(RECKKLAMMER);
  624.                   consume(CSTRING);
  625.                   if token=COMMA then consume(COMMA)
  626.                     else break;
  627.                 until false;
  628.               consume(RECKKLAMMER);
  629.            end
  630.          else usedinproc:=$ffff;
  631.     end;
  632. {$endif}
  633.  
  634.  
  635.         function new_dispose_statement : ptree;
  636.  
  637.           var
  638.                  p,p2 : ptree;
  639.                  ht : ttoken;
  640.          again : boolean; { dummy for do_proc_call }
  641.                  destrukname : stringid;
  642.                  sym : psym;
  643.                  classh : pobjectdef;
  644.                  pd,pd2 : pdef;
  645.                  store_valid : boolean;
  646.                  tt : ttreetyp;
  647.  
  648.           begin
  649.                  ht:=token;
  650.                  if token=_NEW then consume(_NEW)
  651.                    else consume(_DISPOSE);
  652.                  if ht=_NEW then
  653.                    tt:=hnewn
  654.                  else
  655.                    tt:=hdisposen;
  656.                  consume(LKLAMMER);
  657.                  p:=expr;
  658.  
  659.                  { calc return type }
  660.                  cleartempgen;
  661.                  Store_valid := Must_be_valid;
  662.                  Must_be_valid := False;
  663.                  do_firstpass(p);
  664.                  Must_be_valid := Store_valid;
  665.  
  666.          {var o:Pobject;
  667.  
  668.                   begin
  669.                       new(o,init);        (*Also a valid new statement*)
  670.                   end;}
  671.  
  672.                  if token=COMMA then
  673.                    begin
  674.                           { extended syntax of new and dispose }
  675.                           { function styled new is handled in factor }
  676.                           consume(COMMA);
  677.                           { destructors have no parameters }
  678.                           destrukname:=pattern;
  679.                           consume(ID);
  680.  
  681.                           pd:=p^.resulttype;
  682.                           pd2:=pd;
  683.                           if (p^.resulttype = nil) or (pd^.deftype<>pointerdef) then
  684.                             begin
  685.                                Message(parser_e_pointer_type_expected);
  686.                                p:=factor(false);
  687.                                consume(RKLAMMER);
  688.                                new_dispose_statement:=genzeronode(errorn);
  689.                                exit;
  690.                             end;
  691.                           { first parameter must be an object or class }
  692.                           if ppointerdef(pd)^.definition^.deftype<>objectdef then
  693.                             begin
  694.                                Message(parser_e_pointer_to_class_expected);
  695.                                new_dispose_statement:=factor(false);
  696.                                consume_all_until(RKLAMMER);
  697.                                consume(RKLAMMER);
  698.                                exit;
  699.                             end;
  700.                           { check, if the first parameter is a pointer to a _class_ }
  701.                           classh:=pobjectdef(ppointerdef(pd)^.definition);
  702.                           if (classh^.options and oois_class)<>0 then
  703.                                 begin
  704.                                    Message(parser_e_no_new_or_dispose_for_classes);
  705.                                    new_dispose_statement:=factor(false);
  706.                                    { while token<>RKLAMMER do
  707.                                          consume(token); }
  708.                                    consume_all_until(RKLAMMER);
  709.                                    consume(RKLAMMER);
  710.                                    exit;
  711.                                 end;
  712.                           { search cons-/destructor, also in parent classes }
  713.                           sym:=nil;
  714.                           while assigned(classh) do
  715.                                 begin
  716.                                    sym:=classh^.publicsyms^.search(pattern);
  717.                                    srsymtable:=classh^.publicsyms;
  718.                                    if assigned(sym) then
  719.                                          break;
  720.                                    classh:=classh^.childof;
  721.                                 end;
  722.                           { the second parameter of new/dispose must be a call }
  723.                           { to a cons-/destructor                                }
  724.                           if (sym^.typ<>procsym) then
  725.                                 begin
  726.                                    Message(parser_e_expr_have_to_be_destructor_call);
  727.                                    new_dispose_statement:=genzeronode(errorn);
  728.                                 end
  729.                           else
  730.                                 begin
  731.                                   p2:=gensinglenode(tt,p);
  732.                                   if ht=_NEW then
  733.                                         begin
  734.                                            { Constructors can take parameters.}
  735.                                            p2^.resulttype:=ppointerdef(pd)^.definition;
  736.                                            do_member_read(sym,p2,pd,again);
  737.                                         end
  738.                                   else
  739.                                     { destructors can't.}
  740.                                     p2:=genmethodcallnode(pprocsym(sym),srsymtable,p2);
  741.  
  742.                                   { we need the real called method }
  743.                                   cleartempgen;
  744.                                   do_firstpass(p2);
  745.  
  746.                                   if (ht=_NEW) and ((p2^.procdefinition^.options and poconstructor)=0) then
  747.                                          Message(parser_e_expr_have_to_be_constructor_call);
  748.                                   if (ht=_DISPOSE) and ((p2^.procdefinition^.options and podestructor)=0) then
  749.                                          Message(parser_e_expr_have_to_be_destructor_call);
  750.  
  751.                                   if ht=_NEW then
  752.                                         begin
  753.                                                 p2:=gennode(assignn,getcopy(p),gensinglenode(newn,p2));
  754.                                                 p2^.right^.resulttype:=pd2;
  755.                                         end;
  756.                                   new_dispose_statement:=p2;
  757.                                 end;
  758.                    end
  759.                  else
  760.                    begin
  761.                       if (p^.resulttype=nil) or (p^.resulttype^.deftype<>pointerdef) then
  762.                         Begin
  763.                            Message(parser_e_pointer_type_expected);
  764.                            new_dispose_statement:=genzeronode(errorn);
  765.                         end
  766.                       else
  767.                         begin
  768.                            if (ppointerdef(p^.resulttype)^.definition^.deftype=objectdef) then
  769.                             Message(parser_w_use_extended_syntax_for_objects);
  770.  
  771.                             case ht of
  772.                                _NEW : new_dispose_statement:=gensinglenode(simplenewn,p);
  773.                                _DISPOSE : new_dispose_statement:=gensinglenode(simpledisposen,p);
  774.                             end;
  775.                         end;
  776.                    end;
  777.                  consume(RKLAMMER);
  778.           end;
  779.  
  780.     function statement_block : ptree;
  781.  
  782.       var
  783.          first,last : ptree;
  784.  
  785.       begin
  786.          first:=nil;
  787.          consume(_BEGIN);
  788.          while token<>_END do
  789.            begin
  790.               if first=nil then
  791.                 begin
  792.                    last:=gennode(anwein,nil,statement);
  793.                    first:=last;
  794.                 end
  795.               else
  796.                 begin
  797.                    last^.left:=gennode(anwein,nil,statement);
  798.                    last:=last^.left;
  799.                 end;
  800.               if token=_END then
  801.                 break
  802.               else
  803.                 begin
  804.                    { if no semicolon, then error and go on }
  805.                    if token<>SEMICOLON then
  806.                      begin
  807.                         consume(SEMICOLON);
  808.                         { while token<>SEMICOLON do
  809.                           consume(token); }
  810.                         consume_all_until(SEMICOLON);
  811.                      end;
  812.                    consume(SEMICOLON);
  813.                 end;
  814.               emptystats;
  815.            end;
  816.          consume(_END);
  817.          first:=gensinglenode(blockn,first);
  818.          statement_block:=first;
  819.       end;
  820.  
  821.     function statement : ptree;
  822.  
  823.       var
  824.          p : ptree;
  825.          code : ptree;
  826.          labelnr : plabel;
  827.  
  828.       label
  829.          ready;
  830.  
  831.       begin
  832.          case token of
  833.             _GOTO : begin
  834.                        if not(cs_support_goto in aktswitches)then
  835.                         Message(sym_e_goto_and_label_not_supported);
  836.                        consume(_GOTO);
  837.                        if (token<>INTCONST) and (token<>ID) then
  838.                          begin
  839.                             Message(sym_e_label_not_found);
  840.                             code:=genzeronode(errorn);
  841.                          end
  842.                        else
  843.                          begin
  844.                             getsym(pattern,true);
  845.                             consume(token);
  846.                             if srsym^.typ<>labelsym then
  847.                               begin
  848.                                  Message(sym_e_id_is_no_label_id);
  849.                                  code:=genzeronode(errorn);
  850.                               end
  851.                             else
  852.                               code:=genlabelnode(goton,
  853.                                 plabelsym(srsym)^.number);
  854.                          end;
  855.                     end;
  856.             _BEGIN : code:=statement_block;
  857.             _IF    : code:=if_statement;
  858.             _CASE  : code:=case_statement;
  859.             _REPEAT : code:=repeat_statement;
  860.             _WHILE : code:=while_statement;
  861.             _FOR : code:=for_statement;
  862.             _NEW,_DISPOSE : code:=new_dispose_statement;
  863.  
  864.             _WITH : code:=with_statement;
  865.             _TRY : code:=try_statement;
  866.             _RAISE : code:=raise_statement;
  867.             { semicolons,else until and end are ignored }
  868.             SEMICOLON,
  869.             _ELSE,
  870.             _UNTIL,
  871.             _END : code:=genzeronode(niln);
  872.             _CONTINUE : begin
  873.                            consume(_CONTINUE);
  874.                            code:=genzeronode(continuen);
  875.                         end;
  876.             _FAIL : begin
  877.                        { internalerror(100); }
  878.                        if (aktprocsym^.definition^.options and poconstructor)=0 then
  879.                         Message(parser_e_fail_only_in_constructor);
  880.                        consume(_FAIL);
  881.                        code:=genzeronode(failn);
  882.                     end;
  883.             _BREAK:
  884.               begin
  885.                  consume(_BREAK);
  886.                  code:=genzeronode(breakn);
  887.               end;
  888.             _EXIT : code:=exit_statement;
  889.             _ASM : code:=_asm_statement;
  890.          else
  891.            begin
  892.               if (token=INTCONST) or
  893.                 ((token=ID) and
  894.                 not((cs_delphi2_compatible in aktswitches) and
  895.                 (pattern='RESULT'))) then
  896.                 begin
  897.                    getsym(pattern,false);
  898.                    if assigned(srsym) and (srsym^.typ=labelsym) then
  899.                      begin
  900.                         consume(token);
  901.                         consume(COLON);
  902.                         if plabelsym(srsym)^.defined then
  903.                           Message(sym_e_label_already_defined);
  904.                         plabelsym(srsym)^.defined:=true;
  905.  
  906.                         { statement modifies srsym }
  907.                         labelnr:=plabelsym(srsym)^.number;
  908.  
  909.                         { the pointer to the following instruction }
  910.                         { isn't a very clean way                   }
  911. {$ifdef tp}
  912.                         code:=gensinglenode(labeln,statement);
  913. {$else}
  914.                         code:=gensinglenode(labeln,statement());
  915. {$endif}
  916.                         code^.labelnr:=labelnr;
  917.                         { sorry, but there is a jump the easiest way }
  918.                         goto ready;
  919.                      end;
  920.                 end;
  921.               p:=expr;
  922.               if (p^.treetype<>calln) and
  923.                 (p^.treetype<>assignn) and
  924.                 (p^.treetype<>inlinen) then
  925.                 Message(cg_e_illegal_expression);
  926.               code:=p;
  927.            end;
  928.          end;
  929.          ready:
  930.          statement:=code;
  931.       end;
  932.  
  933.     function block(islibrary : boolean) : ptree;
  934.  
  935. {$ifdef TEST_FUNCRET }
  936.       var
  937.          funcretsym : pfuncretsym;
  938. {$endif TEST_FUNCRET }
  939.  
  940.       begin
  941. {$ifdef TEST_FUNCRET }
  942.          if procinfo.retdef<>pdef(voiddef) then
  943.            begin
  944.               { if the current is a function aktprocsym is non nil }
  945.               { and there is a local symtable set }
  946.               funcretsym:=new(pfuncretsym,init(aktprocsym^.name),@procinfo);
  947.               { insert in local symtable }
  948.               symtablestack^.insert(funcretsym);
  949.            end;
  950. {$endif TEST_FUNCRET }
  951.          read_declarations(islibrary);
  952.  
  953.          { temporary space is set, while the BEGIN of the procedure }
  954.          if (symtablestack^.symtabletype=localsymtable) then
  955.            procinfo.firsttemp := -symtablestack^.datasize
  956.          else procinfo.firsttemp := 0;
  957.  
  958.          { space for the return value }
  959.          { !!!!!   this means that we can not set the return value
  960.          in a subfunction !!!!! }
  961.          { because we don't know yet where the address is }
  962.          if procinfo.retdef<>pdef(voiddef) then
  963.            begin
  964.               if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  965.               { if (procinfo.retdef^.deftype=orddef) or
  966.                  (procinfo.retdef^.deftype=pointerdef) or
  967.                  (procinfo.retdef^.deftype=enumdef) or
  968.                  (procinfo.retdef^.deftype=procvardef) or
  969.                  (procinfo.retdef^.deftype=floatdef) or
  970.                  (
  971.                    (procinfo.retdef^.deftype=setdef) and
  972.                    (psetdef(procinfo.retdef)^.settype=smallset)
  973.                  ) then  }
  974.                 begin
  975. {$ifdef TEST_FUNCRET }
  976.                    { the space has been set in the local symtable }
  977.                    procinfo.retoffset:=-funcretsym^.address;
  978.                    strdispose(funcretsym^._name);
  979.                    { lowercase name unreachable }
  980.                    { as it is handled differently }
  981.                    funcretsym^._name:=strpnew('func_result');
  982. {$else  TEST_FUNCRET }
  983.                    procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  984.                    procinfo.firsttemp:=procinfo.retoffset;
  985. {$endif TEST_FUNCRET }
  986.                    if (procinfo.flags and pooperator)<>0 then
  987.                      {opsym^.address:=procinfo.call_offset; is wrong PM }
  988.                      opsym^.address:=procinfo.retoffset;
  989.                    { eax is modified by a function }
  990. {$ifdef i386}
  991.                    usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  992. {$endif}
  993. {$ifdef m68k}
  994.                    usedinproc:=usedinproc or ($800 shr word(R_D0))
  995. {$endif}
  996.                 end;
  997.            end;
  998.  
  999.          {Unit initialization?.}
  1000.          if (lexlevel=1) then
  1001.             if (token=_END) then
  1002.                 begin
  1003.                     consume(_END);
  1004.                     block:=nil;
  1005.                 end
  1006.             else
  1007.                 begin
  1008.                     current_module^.flags:=current_module^.flags or
  1009.                      uf_init;
  1010.                     block:=statement_block;
  1011.                 end
  1012.          else
  1013.             block:=statement_block;
  1014.       end;
  1015.  
  1016.     function assembler_block : ptree;
  1017.  
  1018.       begin
  1019.          read_declarations(false);
  1020.          { temporary space is set, while the BEGIN of the procedure }
  1021.          if symtablestack^.symtabletype=localsymtable then
  1022.            procinfo.firsttemp := -symtablestack^.datasize
  1023.          else procinfo.firsttemp := 0;
  1024.  
  1025.          { assembler code does not allocate }
  1026.          { space for the return value       }
  1027.           if procinfo.retdef<>pdef(voiddef) then
  1028.            begin
  1029.               if ret_in_acc(procinfo.retdef) then
  1030.                 begin
  1031.                    { in assembler code the result should be directly in %eax
  1032.                    procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  1033.                    procinfo.firsttemp:=procinfo.retoffset;                   }
  1034.  
  1035. {$ifdef i386}
  1036.                    usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1037. {$endif}
  1038. {$ifdef m68k}
  1039.                    usedinproc:=usedinproc or ($800 shr word(R_D0))
  1040. {$endif}
  1041.                 end
  1042.               else
  1043.               { should we allow assembler functions of big elements ? }
  1044.                Message(parser_e_asm_incomp_with_function_return);
  1045.            end;
  1046.            { set the framepointer to esp for assembler functions }
  1047.            { but only if the are no local variables              }
  1048.            if ((aktprocsym^.definition^.options and poassembler)<>0) and
  1049.               (aktprocsym^.definition^.parast^.datasize=0) and
  1050.               (aktprocsym^.definition^.localst^.datasize=0) then
  1051.                begin
  1052. {$ifdef i386}
  1053.                   procinfo.framepointer:=R_ESP;
  1054. {$endif}
  1055. {$ifdef m68k}
  1056.                   procinfo.framepointer:=R_SP;
  1057. {$endif}
  1058.                   { set the right value for parameters }
  1059.                   dec(aktprocsym^.definition^.parast^.call_offset,4);
  1060.                   dec(procinfo.call_offset,4);
  1061.               end;
  1062.             assembler_block:=_asm_statement;
  1063.           end;
  1064.  
  1065. end.
  1066. {
  1067.   $Log: pstatmnt.pas,v $
  1068.   Revision 1.3.2.1  1998/08/05 14:07:34  pierre
  1069.     * changed assembler statement so that a stack frame is generated
  1070.       if there are arguments
  1071.  
  1072.   Revision 1.3  1998/03/28 23:09:56  florian
  1073.     * secondin bugfix (m68k and i386)
  1074.     * overflow checking bugfix (m68k and i386) -- pretty useless in
  1075.       secondadd, since everything is done using 32-bit
  1076.     * loading pointer to routines hopefully fixed (m68k)
  1077.     * flags problem with calls to RTL internal routines fixed (still strcmp
  1078.       to fix) (m68k)
  1079.     * #ELSE was still incorrect (didn't take care of the previous level)
  1080.     * problem with filenames in the command line solved
  1081.     * problem with mangledname solved
  1082.     * linking name problem solved (was case insensitive)
  1083.     * double id problem and potential crash solved
  1084.     * stop after first error
  1085.     * and=>test problem removed
  1086.     * correct read for all float types
  1087.     * 2 sigsegv fixes and a cosmetic fix for Internal Error
  1088.     * push/pop is now correct optimized (=> mov (%esp),reg)
  1089.  
  1090.   Revision 1.2  1998/03/26 11:18:31  florian
  1091.     - switch -Sa removed
  1092.     - support of a:=b:=0 removed
  1093.  
  1094.   Revision 1.1.1.1  1998/03/25 11:18:15  root
  1095.   * Restored version
  1096.  
  1097.   Revision 1.21  1998/03/10 16:27:42  pierre
  1098.     * better line info in stabs debug
  1099.     * symtabletype and lexlevel separated into two fields of tsymtable
  1100.     + ifdef MAKELIB for direct library output, not complete
  1101.     + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  1102.       working
  1103.     + ifdef TESTFUNCRET for setting func result in underfunction, not
  1104.       working
  1105.  
  1106.   Revision 1.20  1998/03/10 04:18:26  carl
  1107.    * wrong units were being used with m68k target
  1108.  
  1109.   Revision 1.19  1998/03/10 01:17:25  peter
  1110.     * all files have the same header
  1111.     * messages are fully implemented, EXTDEBUG uses Comment()
  1112.     + AG... files for the Assembler generation
  1113.  
  1114.   Revision 1.18  1998/03/06 00:52:46  peter
  1115.     * replaced all old messages from errore.msg, only ExtDebug and some
  1116.       Comment() calls are left
  1117.     * fixed options.pas
  1118.  
  1119.   Revision 1.17  1998/03/02 01:49:07  peter
  1120.     * renamed target_DOS to target_GO32V1
  1121.     + new verbose system, merged old errors and verbose units into one new
  1122.       verbose.pas, so errors.pas is obsolete
  1123.  
  1124.   Revision 1.16  1998/02/22 23:03:30  peter
  1125.     * renamed msource->mainsource and name->unitname
  1126.     * optimized filename handling, filename is not seperate anymore with
  1127.       path+name+ext, this saves stackspace and a lot of fsplit()'s
  1128.     * recompiling of some units in libraries fixed
  1129.     * shared libraries are working again
  1130.     + $LINKLIB <lib> to support automatic linking to libraries
  1131.     + libraries are saved/read from the ppufile, also allows more libraries
  1132.       per ppufile
  1133.  
  1134.   Revision 1.15  1998/02/21 03:33:54  carl
  1135.     + mit assembler syntax support
  1136.  
  1137.   Revision 1.14  1998/02/13 10:35:29  daniel
  1138.   * Made Motorola version compilable.
  1139.   * Fixed optimizer
  1140.  
  1141.   Revision 1.13  1998/02/12 11:50:30  daniel
  1142.   Yes! Finally! After three retries, my patch!
  1143.  
  1144.   Changes:
  1145.  
  1146.   Complete rewrite of psub.pas.
  1147.   Added support for DLL's.
  1148.   Compiler requires less memory.
  1149.   Platform units for each platform.
  1150.  
  1151.   Revision 1.12  1998/02/11 21:56:39  florian
  1152.     * bugfixes: bug0093, bug0053, bug0088, bug0087, bug0089
  1153.  
  1154.   Revision 1.11  1998/02/07 09:39:26  florian
  1155.     * correct handling of in_main
  1156.     + $D,$T,$X,$V like tp
  1157.  
  1158.   Revision 1.10  1998/01/31 00:42:26  carl
  1159.     +* Final bugfix #60 (working!) Type checking in case statements
  1160.  
  1161.   Revision 1.7  1998/01/21 02:18:28  carl
  1162.     * bugfix 79 (assembler_block now chooses the correct framepointer and
  1163.       offset).
  1164.  
  1165.   Revision 1.6  1998/01/16 22:34:43  michael
  1166.   * Changed 'conversation' to 'conversion'. Waayyy too much chatting going on
  1167.     in this compiler :)
  1168.  
  1169.   Revision 1.5  1998/01/12 14:51:18  carl
  1170.     - temporariliy removed case type checking until i know where the bug
  1171.       comes from!
  1172.  
  1173.   Revision 1.4  1998/01/11 19:23:49  carl
  1174.     * bug fix number 60 (case statements type checking)
  1175.  
  1176.   Revision 1.3  1998/01/11 10:54:25  florian
  1177.     + generic library support
  1178.  
  1179.   Revision 1.2  1998/01/09 09:10:02  michael
  1180.   + Initial implementation, second try
  1181.  
  1182. }
  1183.